using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;


namespace ScytheEngine
{
	/// <summary>
	/// Helper for reading input from keyboard and gamepad. This class tracks both
	/// the current and previous state of both input devices, and implements query
	/// properties for high level input actions such as "move up through the menu"
	/// or "pause the game".
	/// </summary>
	public class InputState
	{
		#region Fields

		public KeyboardState CurrentKeyboardState;
		public GamePadState CurrentGamePadState;

		public KeyboardState LastKeyboardState;
		public GamePadState LastGamePadState;

		#endregion

		#region Properties


		/// <summary>
		/// Checks for a "menu up" input action (on either keyboard or gamepad).
		/// </summary>
		public bool MenuUp
		{
			get
			{
				return IsNewKeyPress( Keys.Up ) ||
					   ( CurrentGamePadState.DPad.Up == ButtonState.Pressed &&
						LastGamePadState.DPad.Up == ButtonState.Released ) ||
					   ( CurrentGamePadState.ThumbSticks.Left.Y > 0 &&
						LastGamePadState.ThumbSticks.Left.Y <= 0 );
			}
		}


		/// <summary>
		/// Checks for a "menu down" input action (on either keyboard or gamepad).
		/// </summary>
		public bool MenuDown
		{
			get
			{
				return IsNewKeyPress( Keys.Down ) ||
					   ( CurrentGamePadState.DPad.Down == ButtonState.Pressed &&
						LastGamePadState.DPad.Down == ButtonState.Released ) ||
					   ( CurrentGamePadState.ThumbSticks.Left.Y < 0 &&
						LastGamePadState.ThumbSticks.Left.Y >= 0 );
			}
		}


		/// <summary>
		/// Checks for a "menu select" input action (on either keyboard or gamepad).
		/// </summary>
		public bool MenuSelect
		{
			get
			{
				return IsNewKeyPress( Keys.Space ) ||
					   IsNewKeyPress( Keys.Enter ) ||
					   ( CurrentGamePadState.Buttons.A == ButtonState.Pressed &&
						LastGamePadState.Buttons.A == ButtonState.Released ) ||
					   ( CurrentGamePadState.Buttons.Start == ButtonState.Pressed &&
						LastGamePadState.Buttons.Start == ButtonState.Released );
			}
		}


		/// <summary>
		/// Checks for a "menu cancel" input action (on either keyboard or gamepad).
		/// </summary>
		public bool MenuCancel
		{
			get
			{
				return IsNewKeyPress( Keys.Escape ) ||
					   ( CurrentGamePadState.Buttons.B == ButtonState.Pressed &&
						LastGamePadState.Buttons.B == ButtonState.Released ) ||
					   ( CurrentGamePadState.Buttons.Back == ButtonState.Pressed &&
						LastGamePadState.Buttons.Back == ButtonState.Released );
			}
		}


		/// <summary>
		/// Checks for a "pause the game" input action (on either keyboard or gamepad).
		/// </summary>
		public bool PauseGame
		{
			get
			{
				return IsNewKeyPress( Keys.Escape ) ||
					   ( CurrentGamePadState.Buttons.Back == ButtonState.Pressed &&
						LastGamePadState.Buttons.Back == ButtonState.Released ) ||
					   ( CurrentGamePadState.Buttons.Start == ButtonState.Pressed &&
						LastGamePadState.Buttons.Start == ButtonState.Released );
			}
		}


		#endregion

		#region Methods


		/// <summary>
		/// Reads the latest state of the keyboard and gamepad.
		/// </summary>
		public void Update()
		{
			LastKeyboardState = CurrentKeyboardState;
			LastGamePadState = CurrentGamePadState;

			CurrentKeyboardState = Keyboard.GetState();
			CurrentGamePadState = GamePad.GetState( PlayerIndex.One );
		}


		/// <summary>
		/// Helper for checking if a key was newly pressed during this update.
		/// </summary>
		bool IsNewKeyPress( Keys key )
		{
			return ( CurrentKeyboardState.IsKeyDown( key ) &&
					LastKeyboardState.IsKeyUp( key ) );
		}


		#endregion
	}
}
